<?xml version="1.0" encoding="UTF-8"?>
<html>
    <head>
        <link type="text/css" rel="stylesheet" href="./css/template.css" />
        <link type="text/css" rel="stylesheet" href="./css/SyntaxHighlighter.css" />
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>JAXB : le data-binding en JAVA</title>
        <script language="javascript" src="./js/shInit.js" />
        <script language="javascript" src="./js/shCore.js" />
        <script language="javascript" src="./js/shBrushCpp.js" />
        <script language="javascript" src="./js/shBrushCSharp.js" />
        <script language="javascript" src="./js/shBrushCss.js" />
        <script language="javascript" src="./js/shBrushDelphi.js" />
        <script language="javascript" src="./js/shBrushJava.js" />
        <script language="javascript" src="./js/shBrushJScript.js" />
        <script language="javascript" src="./js/shBrushPhp.js" />
        <script language="javascript" src="./js/shBrushPython.js" />
        <script language="javascript" src="./js/shBrushRuby.js" />
        <script language="javascript" src="./js/shBrushSql.js" />
        <script language="javascript" src="./js/shBrushVb.js" />
        <script language="javascript" src="./js/shBrushXml.js" />
        <keywords>JAXB, XML, mashal, unmarshal</keywords>
        <keywords />
        <author>Christophe Descottes-Genon</author>
    </head>
    <body>
        <div class="chapter">
            <h2>Introduction</h2>
            <p>Le XML est aujourd'hui un format d'échange de données très utilisé. Il possède de nombreux avantages : il est standard, simple, et surtout facile à lire. Il peut être lu par un homme, mais ce qui est le plus intéressant, c'est qu'il peut être lu par un ordinateur. En effet, la puissance du XML repose sur le fait qu'il peut être analysé par un programme et le contenu de ce flux est compris par la machine. La structure de ce langage permet en effet de comprendre les relations entre toutes ces données.</p>
            <p>De ce fait, les programmeurs ont réalisé de nombreuses API permettant d'accéder aux données XML à travers leurs langages favoris (DOM et SAX par exemple en Java). Néanmoins, ces dernières ont des inconvénients. Tous d'abord, il faut étudier et apprendre une nouvelle API. Puis, ils sont trop généraux. C'est-à-dire que le programmeur doit adapter le code à son application à chaque fois qu'il veut accéder à des données XML. Ensuite, il faut qu'il crée lui-même toutes les classes permettant de gérer ces nouvelles données dans son programme, cela lui prend donc beaucoup de temps.</p>
            <p>
                Pour remédier à ces inconvénients, il existe le « Data Binding » également appelé en français : association de données. En java, Sun a réalisé une API nommée JAXB (Java Architecture for XML Binding). Cette API ainsi que sa documentation sont disponibles dans le JWSDP2 (
                <b>J</b>
                ava
                <b>W</b>
                eb
                <b>S</b>
                ervices
                <b>D</b>
                evelopper
                <b>P</b>
                ack 2) sur le site de Sun aux adresses suivantes :
            </p>
            <p>
                <a href="http://java.sun.com/xml/jaxb/" target="_about">Documentation JAXB.</a>
            </p>
            <p>
                <a href="http://java.sun.com/webservices/downloads/previous/webservicespack.jsp" target="_about">JWSDP2 : API, documentation, installation et tutorial.</a>
            </p>
            <p>
                <b>Note</b>
                : Pour que JAXB fonctionne, il faut une machine virtuelle JAVA
            </p>
            <p>Le but de cet article est de comprendre comment fonctionne le « Data Binding » et comment le mettre en place en Java avec l'API JAXB. Nous verrons un aperçu de son installation et de son utilisation.</p>
        </div>
        <!-- Fin du chapitre introduction -->
        <div class="chapter">
            <h2>Qu'est ce que le « Data Binding » ou association de données ?</h2>
            <p>Le Data Binding est une technologie permettant d'automatiser la transformation d'un modèle de données en un modèle de données objets dans un langage de programmation. Autrement dit, il permet par exemple de convertir les fichiers XML en instances de classes Java.</p>
            <p>Pour réaliser cela, il y a trois étapes :</p>
            <p>
                <b>- La génération de classes</b>
            </p>
            <p>
                <b>- Le rassemblement des données</b>
            </p>
            <p>
                <b>- La redistribution des données</b>
            </p>
            <p>
                <img src="./images/jaxbFonctionnement.jpg" />
            </p>
            <p>Le schéma suivant résume assez bien le principe : un document XML suit les règles de grammaire du « schéma », ce dernier une fois compilé permet de créer une classe correspondante. Cette dernière permettra de créer une instance d'objet correspondant.</p>
            <p>
                <b>Note</b>
                : Pour illustrer le fonctionnement et l'utilisation de JAXB, nous allons utiliser durant tout l'article, un exemple fournit par SUN dans le dossier
                <b>[Dossier_install_de_JWSDP2]/jaxb/samples/unmarshal-read</b>
            </p>
            <div class="subChapter">
                <h3>La génération de classes</h3>
                <p>La première étape pour le « data binding » est de générer les classes qui permettront d'accéder aux données contenues dans les fichiers XML.</p>
                <p>
                    Pour cela, nous devons posséder un fichier
                    <b>XSD</b>
                    . Ce dernier représente
                    <b>la grammaire d'un fichier XML</b>
                    . Voici un extrait du fichier
                    <b>po.xsd</b>
                    de l'exemple
                    <b>
                        <i>unmarshal-read</i>
                    </b>
                    :
                </p>
                <textarea name="code" class="xml">
                    <xsd:complextype xmlns:xsd="xsd" name="USAddress">
                        <xsd:sequence>
                            <xsd:element name="name" type="xsd:string" />
                            <xsd:element name="street" type="xsd:string" />
                            <xsd:element name="city" type="xsd:string" />
                            <xsd:element name="state" type="xsd:string" />
                            <xsd:element name="zip" type="xsd:decimal" />
                        </xsd:sequence>
                        <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US" />
                    </xsd:complextype>
                </textarea>
                <p>Dans cet exemple, facile à comprendre, nous pouvons distinguer le fait qu'il s'agit de la déclaration d'une structure « USAddress ». Cette dernière est également constituée de cinq variables : 4 string  et 1 decimal .</p>
                <p>Le but de la génération de classes est donc d'obtenir une entité contenant ces 5 éléments. En JAVA, il faudrait donc déclarer une classe USAddress de la manière suivante :</p>
                <textarea name="code" class="java">public class USAddress {
					protected java.lang.String _State;
					protected java.math.BigDecimal _Zip;
					protected java.lang.String _Country;
					protected java.lang.String _City;
					protected java.lang.String _Street;
					protected java.lang.String _Name;
					}</textarea>
                <p>De plus il faudrait implémenter les méthodes permettant d'accéder à toutes ces données.</p>
                <p>
                    Ceci est le travail d'un programme contenu dans JAXB :
                    <b>xjc</b>
                    . Nous en parlerons plus en détails dans le chapitre suivant.
                </p>
            </div>
            <!-- Fin du sous chapitre génération de classe -->
            <div class="subChapter">
                <h3>Le rassemblement des données</h3>
                <p>
                    Le rassemblement des données (unmarshall en anglais) permet donc d'instancier les classes précédemment crée avec les données contenues dans les fichiers XML. En d'autre termes, il permet par exemple de faire la traduction :
                    <b>XML =&gt; JAVA</b>
                    .
                </p>
                <p>Pour cela, il faut utiliser un rassembleur (unmarshaller). Ce dernier va vérifier que les données qu'il reçoit sont bien celles attendues. Si ce n'est pas le cas, des exceptions peuvent survenir.</p>
            </div>
            <!-- Fin du sous chapitre Rassemblement de données -->
            <div class="subChapter">
                <h3>La redistribution des données</h3>
                <p>
                    Comme vous pouvez vous en doutez, la redistribution des données consiste à récupérer le contenu de chaque instance de classe et de les insérer dans les fichiers XML. Il s'agit par exemple de faire la traduction
                    <b>JAVA =&gt; XML</b>
                </p>
                <p>Comme pour le rassemblement, pour la redistribution, nous disposons d'un distributeur (marshaller). Ce dernier est chargé de vérifier l'intégrité des données qu'il transporte. Si une erreur intervient, il pourra lever des exceptions</p>
            </div>
            <!-- fin du sous chapitre redistribution des données -->
        </div>
        <!-- Fin du chapitre le Data Binding, c'est quoi -->
        <div class="chapter">
            <h2>Utilisation de JAXB</h2>
            <div class="subChapter">
                <h3>La génération des classes avec XJC</h3>
                <p>Comme il l'a été mentionné dans le premier chapitre, l'utilitaire livré dans JAXB qui est chargé de générer les classes est : xjc. Nous allons étudier de quelles manières il fonctionne.</p>
                <p>Pour en comprendre le fonctionnement nous allons nous intéresser, comme préciser précedemment dans une note, à un exemple fourni : unmarshal-read.</p>
                <h4>Tout d'abord comment fonctionne xjc ?</h4>
                <p>Lorsque l'on demande de l'aide sur un terminal on obtient les informations suivantes :</p>
                <p>
                    <img src="./images/manXJC.png" />
                </p>
                <p>Grâce à cette aide, nous savons que pour transformer un fichier XSD ou schéma il suffit de le mettre en entrée dans ce programme, et de définir un package de sortie avec l'option -p.</p>
                <p>
                    Pour transformer le fichier exemple (
                    <b>po.xsd</b>
                    ) contenu dans le répertoire unmarshal-read cité plus haut, nous avons donc plus qu'à exécuter la commande suivante :
                </p>
                <p>
                    <b>
                        <i>[JWSDP2_INSTALL_DIR]/jaxb/bin/xjc.sh po.xsd -p primer.po</i>
                    </b>
                </p>
                <p>
                    <b>Note</b>
                    :  Pour la commande précédente, il faut être situé dans le dossier
                    <b>unmarshal-read</b>
                    . Si vous êtes sous Windows, utilisé le script
                    <b>xjc.bat</b>
                    .
                </p>
                <p>Cette commande donne le résultat suivant :</p>
                <p>
                    <img src="./images/classConstruction.png" />
                </p>
                <p>
                    Nous nous apercevons que des classes ont été générées. Elles correspondent aux différents éléments contenus dans le fichier XSD. Elles sont crées dans dossier
                    <b>unmarshal-read/primer/po/</b>
                    .  Cela a donc fonctionné. Nous pouvons donc passer à la programmation proprement dite.
                </p>
            </div>
            <!-- fin de sous chapitre utilisation de XJC -->
            <div class="subChapter">
                <h3>Utilisation des classes créent précédemment pour utiliser les données du fichier XML et en injecter de nouvelles.</h3>
                <h4>Création d'un projet</h4>
                <p>
                    Nous allons commencer par créer un projet java avec une classe
                    <b>Main</b>
                    identique à celle de l'exemple
                    <b>unmarshal-read</b>
                    (emplacement :
                    <b>.../jaxb/samples/unmarshal-read/src/Main.java</b>
                    ).
                </p>
                <p>
                    Ensuite créer un package
                    <i>
                        <b>primer.po</b>
                    </i>
                    et copier y les classes précedemment générées par XJC.
                </p>
                <p>
                    Enfin copier le fichier
                    <b>po.xml</b>
                    (
                    <b>.../jaxb/samples/unmarshal-read/po.xml</b>
                    ) qui contient les données que l'on souhaite utiliser, à la racine du répertoire qui contient le projet.
                </p>
                <h4>Les imports</h4>
                <p>
                    La classe
                    <b>Main</b>
                    contient différents
                    <i>packages</i>
                    lié à JAXB et nécessaires à son bon fonctionnement :
                </p>
                <p>
                    <b>Note</b>
                    : Ces librairies sont contenus dans le répertoire
                    <b>[JWSDP2_INSTALL_DIR]/jaxb/lib/</b>
                    , il faut les importer dans le projet pour pouvoir utiliser les classes qu'ils contiennent. Sous Eclipse :
                    <b>Clic droit sur le projet --&gt; Properties --&gt; Java Build Path --&gt; Librairies --&gt; Add external Jars</b>
                    .
                </p>
                <p>
                    <b>javax.xml.bind</b>
                </p>
                <p>Il définit les classes abstraites et les interfaces. C'est dans ce package que sont regroupés les principaux éléments comme les « unmarshaller » et les « marshaller ».</p>
                <p>De même, c'est dans ce dernier que se trouve le JAXBContext. Ce dernier est le point d'entrée dans tout programme java utilisant JAXB. C'est grâce à ce dernier que l'on peut agir sur les différents éléments de l'API.</p>
                <p>
                    <b>javax.xml.bind.util</b>
                </p>
                <p>Ce package contient toutes les classes outils qui peuvent être utilisées par les applications clients pour le regroupement et la distribution de données.</p>
                <h4>Le rassemblement de donnée</h4>
                <p>Nous allons voir un extrait de la méthode main() commenté, cette première partie montre comment récupéré les données du fichier XML sous forme d'instance d'objet :</p>
                <textarea name="code" class="java">
                    import java.io.FileInputStream;
					import java.io.IOException;
					import java.util.Iterator;
					import java.util.List;
					import javax.xml.bind.JAXBContext;
					import javax.xml.bind.JAXBElement;
					import javax.xml.bind.JAXBException;
					import javax.xml.bind.Unmarshaller;
					// import java content classes generated by binding compiler
					import primer.po.*;
					public class Main {
					public static void main( String[] args ) {
					try {
					//On crée un JAXBContext jc capable de gérer les classes précédemment
					//générées par XJC et contenues dans le package primer.po
					JAXBContext jc = JAXBContext.newInstance( "primer.po" );
					// A l'aide de cet objet on crée un Unmarshaller, objet qui va permettre
					//de convertir les données XML en Objet.
					Unmarshaller u = jc.createUnmarshaller();
					// unmarshal a po instance document into a tree of Java content
					// objects composed of classes from the primer.po package.
					// Les données XML provenant du fichier po.xml sont stocké dans une "liste"
					JAXBElement
					&lt;?&gt; poElement = (JAXBElement
					&lt;?&gt;)u.unmarshal( new FileInputStream( "po.xml" ) );
					// on se sert de cette "liste" pour générer un objet qui va contenir
					// toutes les informations à partir de la balise mère du document XML
                    <purchaseorder>PurchaseOrderType po = (PurchaseOrderType)poElement.getValue();
						System.out.println( "Ship the following items to: " );
						// on peut par exemple récupérer et modifier l'adresse de livraison
						// on remarque que le nom de l'objet USAddress est le même que dans le schéma XSD
						USAddress address = po.getShipTo();
						displayAddress( address );
						// ou bien les informations sur les sous balilses ( les machandises)
						Items items = po.getItems();
						displayItems( items );
						} catch( JAXBException je ) {
						je.printStackTrace();
						} catch( IOException ioe ) {
						ioe.printStackTrace();
						}
						}
						public static void displayAddress( USAddress address ) {
						// display the address
						System.out.println( "\t" + address.getName() );
						System.out.println( "\t" + address.getStreet() );
						System.out.println( "\t" + address.getCity() +
						", " + address.getState() +
						" "  + address.getZip() );
						System.out.println( "\t" + address.getCountry() + "\n");
						}
						public static void displayItems( Items items ) {
						// the items object contains a List of primer.po.ItemType objects
						List itemTypeList = items.getItem();
						// iterate over List
						for( Iterator iter = itemTypeList.iterator(); iter.hasNext(); ) {
						Items.Item item = (Items.Item)iter.next();
						System.out.println( "\t" + item.getQuantity() +
						" copies of \"" + item.getProductName() +
						"\"" );
						}
						}
						}</purchaseorder>
                </textarea>
                <p>
                    <b>Note</b>
                    : Pour crée la liste d'objet
                    <b>JAXBElements</b>
                    à partir du fichier
                    <b>po.xml</b>
                    (ligne 36), il faut ajouter la librairie
                    <a href="http://dist.codehaus.org/stax/jars/" target="_about">Stax API</a>
                    pour que le programme puisse reconnaître le type
                    <i>XMLStreamReader</i>
                </p>
                <p>Nous avons vu qu'il est facile de récupérer les données d'un fichier XML sous forme d'objets pour les consulter ou les modifier. S'il y a modification, il est important de pouvoir retransformer les objet en fichier XML ( Marshaller).</p>
                <h4>La redistribution des données</h4>
                <p>Tous se passent de la même manière que pour le rassemblement de données.</p>
                <p>Il faut passer par la méthode marshall. Pour cela, il faut créer un objet marshaller par l'intermédiaire de la commande suivante :</p>
                <textarea name="code" class="java">Marshaller m = jc.createMarshaller();</textarea>
                <p>Puis, il faut indiquer de quel type seront les données. Pour cela, on place la propriété FORMATED OUTPUT à true pour que cela soit lisible.</p>
                <textarea name="code" class="java">m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );</textarea>
                <p>Puis, il suffit d'écrire les données dans le descripteur</p>
                <textarea name="code" class="java">m.marshal( po, System.out );</textarea>
                <p>De cette manière il est simple de renvoyer les données crées ou modifiées dans un programme.</p>
            </div>
            <!--fin du sous chapitre utilisation des classes -->
        </div>
        <!-- Fin du chapitre utilisation de JAXB -->
        <div class="chapter">
            <h2>Conclusion</h2>
            <p>Le « data binding » ou « association de données » permet de développer très rapidement des logiciels qui ont besoin d'utiliser des données contenues dans des fichiers XML.
				Son implémentation en JAVA : Java Architecture for XML Binding (JAXB) est simple d'utilisation.
				Tous à vos claviers !</p>
        </div>
    </body>
</html>

